/*
 * File : cutter_server.cpp
 * Author : beijixuexiong
 * Date : 2009-03-29
 * */

//#include <concurrency/ThreadManager.h>
//#include <concurrency/PosixThreadFactory.h>

#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <server/TThreadPoolServer.h>
#include <server/TThreadedServer.h>
#include <transport/TServerSocket.h>
#include <transport/TTransportUtils.h>

#include <string>
#include <vector>
#include <iostream>
#include <fstream>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

#include "ICTCLAS30.h"
#include "./gen-cpp/Cutter.h"

using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;

using namespace boost;

#define UMASK (S_IWGRP | S_IWOTH)

const int PORT = 9090;
string WORK_DIR = "/home/vonbo/project/thrift-ictclas";

ofstream server_log("server.log", ios::app);
const char* REDIRECT_TO = "/dev/null";

class CutterHandler: public CutterIf{
	public:
		CutterHandler() {}
		virtual ~CutterHandler() {}
	public:
		void ping() { server_log << "ping" << endl;}

		bool import_dict(const string& filename)
		{
			return ICTCLAS_ImportUserDict(filename.c_str());
		}

		void process(string& _return, const string& str, const bool tagged)
		{
			_return = ICTCLAS_ParagraphProcess(str.c_str(), tagged); 
			//record log
			server_log << "Proc:" << str << endl;
		}

		void process_ret_list(vector<Word>& _return, const string& str)
		{
			int count = 0;
			const result_t* re = ICTCLAS_ParagraphProcessA(str.c_str(), &count);
			for (int i=0; i<count; i++)
			{
				Word myword;
				this->copy_result_t(myword, str, re[i]);
				_return.push_back(myword);
			}
			//record log
			server_log << "Proc:" << str << endl;
		}

		bool add_user_word(const string& word)
		{
			server_log << "AddW:" << word << endl;
			return ICTCLAS_AddUserWord(word.c_str());
		}

		bool del_user_word(const string& word)
		{
			int result = ICTCLAS_DelUsrWord(word.c_str());
			server_log << "DelW:" << word << endl;
			if (result == -1) return false;
			return true;
		}

		int64_t fingerprint()
		{
			return ICTCLAS_FingerPrint();
		}

		void keyword(vector<Word>& _return, const string& str, const int32_t count)
		{
			result_t* result_key  = new result_t[count];
			int count_key = 0;
			ICTCLAS_KeyWord(result_key, count_key);
			for (int i=0; i<count_key; i++)
			{
				Word myword;
				copy_result_t(myword, str, result_key[i]);
				_return.push_back(myword);
			}
			delete [] result_key;
		}

		void shutdown()
		{
			exit(0);
		}


	protected:
		void copy_result_t(Word& _word, const string& str, const result_t& t)
		{
			_word.word = str.substr(t.start, t.length);
			_word.type = string(&t.sPOS[0]);
			_word.id = t.word_ID;
			_word.dict_type = t.word_type;
			_word.weight = t.weight;
		}

};

int main(int argc, char *argv[]) 
{

	int pid = fork();
	if (pid > 0) { exit(0);	}
	setsid();
	pid = fork();
	if (pid > 0) { exit(0); }

	chdir(WORK_DIR.c_str());
	umask(UMASK);

	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);

	int redirect_file = open(REDIRECT_TO, O_RDWR | O_APPEND);
	dup2(redirect_file, STDOUT_FILENO);
	dup2(redirect_file, STDERR_FILENO);

	server_log << "Start server..." << endl;
	if (!ICTCLAS_Init("./"))
	{
		server_log << "Init Failed!" << endl;
		return 1;
	}
	server_log << "Init ictclas success!" << endl;

	shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
	shared_ptr<CutterHandler> handler(new CutterHandler());
	shared_ptr<TProcessor> processor(new CutterProcessor(handler));
	shared_ptr<TServerTransport> serverTransport(new TServerSocket(PORT));
	shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());

	TSimpleServer server(processor,
			serverTransport,
			transportFactory,
			protocolFactory);

	server_log << "Begin listening" << endl;
	server.serve();

	close(redirect_file);
	ICTCLAS_Exit();
	server_log << "Shutdown the server" << endl;
	return 0;
}
